package task;

import edu.buaa.act.helper.Utils;
import edu.buaa.act.model.GPSPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by T7810 on 2017/5/28.
 */
public class BasicStatisticUCar
{
    private static Logger log = Utils.getDebugLogger();

    public static void main(String[] args)
    {
        try{
            File dataDir = new File("D:\\data\\sjhData");

//            List<File> files = getGPSFiles(dataDir);
//            log.trace("data set contains {} cars.", files.size());
//            long totalSize = 0;
//            for(File f : files){
//                totalSize += f.length();
//            }
//            log.trace("total data size is {}", totalSize/1024f/1024f/1024f);
//            uniqueCarCount(files);

            heatmap(new File("D:\\data\\sjhData\\heatmap.csv"), readRawDataFile(getMergedFiles(dataDir)), 1000, 1000);

//            readRawDataFile(files);

        }catch (Throwable e){
            e.printStackTrace();
        }
    }

    private static void heatmap(File file, List<GPSPoint> data, int width, int height) {
        log.debug("cut to {}x{} (width x height)", width, height);
        double maxLat = 0, minLat = 0, maxLon = 0, minLon = 0;
        for(int i=0; i<data.size(); i++){
            GPSPoint p = data.get(i);
            if(i==0){
                maxLat = p.getLatitude();
                minLat = p.getLatitude();
                maxLon = p.getLongitude();
                minLon = p.getLongitude();
            }else{
                if(p.getLatitude()>maxLat) maxLat = p.getLatitude();
                if(p.getLatitude()<minLat) minLat = p.getLatitude();
                if(p.getLongitude()>maxLon) maxLon = p.getLongitude();
                if(p.getLongitude()<minLon) minLon = p.getLongitude();
            }
        }

        log.info("latitude: {} - {}, longitude: {} - {}", minLat, maxLat, minLon, maxLon);
        double wStep = (maxLon - minLon)/width;
        double hStep = (maxLat - minLat)/height;
        log.debug("longitude(w)step: {}, latitude(h)step: {}", wStep, hStep);


    }

    private static List<File> getMergedFiles(File dataDir) {
        String pattern = "\\d{4}-\\d{2}-\\d{2}\\.gps\\.txt";
        final Pattern r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);

        List<File> result = new ArrayList<File>();
        File[] files = dataDir.listFiles(new FilenameFilter()
        {
            @Override
            public boolean accept(File dir, String name)
            {
                Matcher m = r.matcher(name);
                return m.find();
            }
        });
        if(files!=null) {
            result.addAll(Arrays.asList(files));
            return result;
        }else{
            throw new RuntimeException("file not found.");
        }
    }

    private static void uniqueCarCount(List<File> dir)
    {
        String pattern = "(\\d+)_gps.txt";
        final Pattern r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);

        Set<String> carID = new HashSet<>();
        for (File f : dir) {
            Matcher m = r.matcher(f.getName());
            if (m.find()) {
                carID.add(m.group(1));
            }
        }

        log.info("{} unique cars in data set", carID.size());
    }

    private static List<File> getGPSFiles(File dir)
    {
        String pattern = "\\d+_gps.txt";
        final Pattern r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);

        List<File> result = new ArrayList<File>();
        File[] files = dir.listFiles(new FilenameFilter()
        {
            @Override
            public boolean accept(File dir, String name)
            {
                Matcher m = r.matcher(name);
                return m.find();
            }
        });

        if(files==null || files.length==0){
            files = dir.listFiles();
            if(files!=null) {
                for (File subDir : files) {
                    if (subDir.isDirectory()) {
                        result.addAll(getGPSFiles(subDir));
                    }
                }
            }
        }else{
            result.addAll(Arrays.asList(files));
        }

        return result;
    }

    private static List<GPSPoint> readRawDataFile(List<File> inputFiles) throws IOException
    {
        log.trace("start to read {} files", inputFiles.size());
        List<GPSPoint> list = new ArrayList<>(1007_0000);

        long entryCount = 0;

        for(File f : inputFiles)
        {
            BufferedReader ir = new BufferedReader(new FileReader(f));
            String lineTxt;
            boolean firstLine=true;
            while((lineTxt = ir.readLine()) != null) {
                if(firstLine){
                    firstLine=false;
                }else{
                    if(lineTxt.startsWith("latitude")) continue;
                    String[] arr = lineTxt.split(",");
                    double latitude = Double.parseDouble(arr[0]);
                    long carNo = Long.parseLong(arr[1]);
                    float speed = Float.parseFloat(arr[2]);
                    double longitude = Double.parseDouble(arr[3]);
                    int angle = Integer.parseInt(arr[4]);
                    // 5 is accuracy
                    // 6 is height
                    // 7 is position mode
                    long timeStampSecond = Integer.parseInt(arr[8]);
                    entryCount++;
//                    list.add(new GPSPoint(carNo, timeStampSecond*1000, longitude, latitude, speed, angle));
                }
            }
            ir.close();

        }
        log.debug("data file read done. {} entries", entryCount);
//        System.exit(0);
        return list;
    }
}
